<?php

namespace App\services\v1;

use App\Common\RedisCache\SignRecordCache;
use App\Models\UserSign;
use App\services\BaseServices;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;

class SignRecordServices extends BaseServices
{
    /**
     * @var int|string|null
     */
    private $userId;
    /** @var SignRecordCache  */
    private $cache;
    //签到开始时间
    private $signStartTime;

    public function __construct()
    {
        parent::__construct();
        $this->userId = Auth::id() ?: 0;
        $this->cache         = new SignRecordCache();
        $this->cache->setKeyParameter([$this->userId]);
        $this->signStartTime = config('project.sign_start_time');
    }

    /**
     * redis-mapbit 处理签到
     * @return array
     * @throws \RedisException
     */
    public function setSign():array
    {
        $nowTime       = date('Ymd',time());
        return $this->userSign($nowTime);
    }

    /**
     * redis-mapbit 当月签到数据
     * @return array
     * @throws \RedisException
     */
    public function getSignDays():array
    {
        //签到次数
        $signCount = $this->cache->bitCount();
        //当月签到记录
        $nowTime   = date('Ymd',time());
        $oneDay    = date('Ym01');
        $bitCount  = $nowTime - $oneDay;
        for ($i = 0; $i <= $bitCount; $i++) {
            //是否签到
            $data[$i+1] = $this->cache->get('', $oneDay + $i - $this->signStartTime);
        }
        $data['signCount']     = $signCount;
        $this->resData['data'] = $data;
        return $this->resData;
    }

    /**
     * redis-mapbit 处理补签到
     * @param int $counterDay
     * @return array
     */
    public function setCounterSign(int $counterDay):array
    {
       return $this->userSign($counterDay);
    }

    /**
     * redis-bitmap 签到
     * @param int $counterDay
     * @return array
     * @throws \RedisException
     */
    public function userSign(int $counterDay):array
    {
        //不能小于初始时间
        if ($counterDay - $this->signStartTime < 0) {
            $this->resData['code'] = 110003;
            return $this->resData;
        }
        //签到日期
        $counterOffset = $counterDay - $this->signStartTime;
        //避免重复签到
        if($this->cache->get('', $counterOffset)) {
            $this->resData['code'] = 110001;
            return $this->resData;
        }
        $this->cache->set($counterOffset);
        return $this->resData;
    }

    /**
     * mysql 签到
     * @return array
     */
    public function signMysqlAlgorithm()
    {
        //本月总天数
        $monthDays = date('t');
        //今天第几天
        $nowDay    = date('d');
        $nowMonth  = date('Ym');
        $firstBit  = '1';
        $monthIsSign   = $this->userIsMysqlSign($nowMonth);
        //用户本月签到过修改sign_record位
        if ($monthIsSign) {
            $signRecord = decbin($monthIsSign->sign_record);
            //已签过到
            if ($signRecord[(int)$nowDay]) {
                $this->resData['code'] = 110001;
                return  $this->resData;
            }
            $signRecord[(int)$nowDay] = 1;
            //连续签到
            $signCount = $monthIsSign->sign_count;
            if ($signRecord[(int)$nowDay-1]) {
                $monthIsSign->sign_count  = $signCount + 1;
            }
            $monthIsSign->sign_record = bindec($signRecord);
        }
        //用户本月没签到过 新增签到数据
        if ($monthIsSign === null) {
            $monthIsSign = new UserSign();
            //第一bit是1 除今天所有的bit都是0
            for ($i = 1; $i <= $monthDays; $i++) {
                //拼接今天的bit
                if ($i == $nowDay) {
                    $firstBit .= '1';
                    continue;
                }
                $firstBit .= '0';
            }
            $monthIsSign->key_id         = $nowMonth . $this->userId;
            $monthIsSign->user_id        = $this->userId;
            $monthIsSign->sign_record    = bindec($firstBit);
            $monthIsSign->sign_month     = $nowMonth;
            $monthIsSign->sign_count     = 1;
        }
        $monthIsSign->last_sign_date = date('Y-m-d');
        $this->resData['data'] = $monthIsSign->save();
        return $this->resData;
    }

    /**
     * mysql 用户当月是否签到
     * @return UserSign|Builder|Model|object|null
     */
    public function userIsMysqlSign($nowMonth)
    {
        $monthIsSign = UserSign::query()->whereUserId($this->userId)->whereSignMonth($nowMonth)->first();
        return $monthIsSign;
    }

    public function signMysql()
    {

    }

    public function counterSignMysql()
    {

    }
}